JLOI2009 二叉树问题

这道题用到了树的一些概念,但主要算法还是搜索和模拟,我用了深搜(Deep First Search,简称DFS)。

主要思路:
1.用一个结构体来表示树,l表示左子树,r表示右子树,fa表示父节点,ceng表示当前节点的深度,数组下标表示当前节点的值。
2.深度用maxx来表示,每求出一个节点的ceng,就与maxx比较,取大者为maxx,最后的maxx即为深度。
3.宽度用一个数组num来记,假设下标为i,num[i]即为第i层有几个节点,通过扫描所有节点来记,记完后sort从大到小一遍,num[1]即为宽度。
4.计算距离用dfs函数,参数为now(当前节点),up(上行的次数),down(下行的次数),加上简单的剪枝,求出结果ans=up*2+down。
具体解释见代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct tree//树,见思路
{
int fa;
int l;
int r;
int ceng;
}t[787878];
int n,u,v,ans,maxx=-7878;//n个节点,计算从u到v的距离,ans为距离,maxx为深度
int num[787878];//计算宽度,见思路
bool pd[787878];//用来dfs剪枝
bool cmp(int a,int b)//sort从大到小函数
{
return a>b;
}
void dfs(int now,int up,int down)//计算从u到v的距离
{
if(now==v)//到达终点
{
ans=up*2+down;//计算距离
return;
}
if(now<1||now>n) return;//剪枝
pd[now]=true;//记录
if(t[now].l>=1&&t[now].l<=n&&pd[t[now].l]==false) dfs(t[now].l,up,down+1);//搜索左子树,下行次数+1
if(t[now].r>=1&&t[now].r<=n&&pd[t[now].r]==false) dfs(t[now].r,up,down+1);//搜索右子树,下行次数+1
if(t[now].fa>=1&&t[now].fa<=n&&pd[t[now].fa]==false) dfs(t[now].fa,up+1,down);//搜索父节点,上行次数+1
}
int main()//主函数
{
scanf("%d",&n);//输入
t[1].fa=0; t[1].ceng=1;//处理根节点
for(int i=1;i<=(n-1);i++)
{
int x,y;
scanf("%d%d",&x,&y);//输入
if(t[x].l==0) t[x].l=y;
else t[x].r=y;//记录左右子树
t[y].fa=x;//记录父节点
t[y].ceng=t[x].ceng+1;//记录层数
maxx=max(maxx,t[y].ceng);//计算深度
}
scanf("%d%d",&u,&v);//输入
for(int i=1;i<=n;i++)
num[t[i].ceng]++;//计算每一层节点的数量
sort(num+1,num+n+1,cmp);//排序,找出宽度
dfs(u,0,0);//搜索从u到v的距离
printf("%d\n%d\n%d",maxx,num[1],ans);//输出
return 0;//程序结束
}

希望我的代码能够帮助到大家!